//package cn.tedu.csmall.resource.config;
//
//import cn.tedu.csmall.commons.web.JsonResult;
//import cn.tedu.csmall.commons.web.ServiceCode;
//import cn.tedu.csmall.resource.filter.JwtAuthorizationFilter;
//
//import com.alibaba.fastjson.JSON;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration;
//
//import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//import org.springframework.security.config.http.SessionCreationPolicy;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.web.AuthenticationEntryPoint;
//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
//
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.io.PrintWriter;
//
//@Slf4j
//@Configuration
//@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启全局的基于方法的安全检查，即：在方法上添加注解来检查权限
//public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
//
//
//    @Autowired
//    private JwtAuthorizationFilter jwtAuthorizationFilter;
//
//
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        // 开启Spring Security自带的CorsFilter，以解决跨域问题
//        http.cors();
//
//        // 配置Spring Security框架使用（创建）Session的策略
//        // STATELESS：无状态的，完全不使用Session
//        // NEVER：从不主动创建Session，但是，当Session已经被创建后，仍会正常使用
//        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//
//        // 将JWT过滤器添加到Spring Security框架的某些过滤器之前
//        http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);
//
//        // 处理未通过认证时访问受保护的资源时拒绝访问
//        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
//            @Override
//            public void commence(HttpServletRequest request, HttpServletResponse response,
//                                 AuthenticationException e) throws IOException, ServletException {
//                String message = "您当前未登录，请先登录！";
//                log.warn(message);
//
//                JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED, message);
//                String jsonString = JSON.toJSONString(jsonResult);
//
//                response.setContentType("application/json; charset=utf-8");
//                PrintWriter printWriter = response.getWriter();
//                printWriter.println(jsonString);
//                printWriter.close();
//            }
//        });
//
//        // 禁用“防止伪造的跨域攻击的防御机制”
//        http.csrf().disable();
//
//        // 白名单
//        // 使用1个星号，可以通配此层级的任何资源，例如：/admin/*，可以匹配：/admin/add-new、/admin/list，但不可以匹配：/admin/password/change
//        // 使用2个连续的星可以，可以通配若干层级的资源，例如：/admin/**，可以匹配：/admin/add-new、/admin/password/change
//        String[] urls = {
//                "/doc.html",
//                "/**/*.css",
//                "/**/*.js",
//                "/swagger-resources",
//                "/v2/api-docs"
//        };
//
//        // 配置授权访问
//        // 注意：以下授权访问的配置，是遵循“第一匹配原则”的，即“以最先匹配到的规则为准”
//        // 例如：anyRequest()是匹配任何请求，通常，应该配置在最后，表示“除了以上配置过的以外的所有请求”
//        // 所以，在开发实践中，应该将更具体的请求配置在靠前的位置，将更笼统的请求配置在靠后的位置
//        http.csrf().disable().authorizeRequests() // 开始对请求进行授权
//                .mvcMatchers(urls) // 匹配某些请求
//                .permitAll() // 许可，即不需要通过认证就可以访问
//                .anyRequest() // 任何请求
//                .authenticated(); // 要求已经完成认证的
//
//        // super.configure(http); // 不要保留调用父级同名方法的代码，不要保留！不要保留！不要保留！
//
//        // 1.如果调用以下方法，当Security认为需要通过认证，但实际未通过认证时，就会跳转到登录页面
//        //    一.没有配置上面的权限部分时，默认的是允许get请求，只会对post请求做认证
//        //       页面都能正常打开，get请求也能返回内容，文档页面操作post请求会返回403
//        //    二.配置上面的权限部分后，会认证所有请求包括get，浏览器输入没有放行的地址
//        //      会跳到login登录页面，文档页面操作会返回login页面的html代码
//        // 2.如果未调用以下方法，将会响应403错误
//        //   不会有login登录页面，不会调到登录页面，直接返回403
//        http.formLogin();
//    }
//}
